package de.homelabs.modules.template.service;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import de.homelabs.modules.template.domain.HLTemplateElement;
import de.homelabs.modules.template.domain.HLTemplateList;
import de.homelabs.modules.tools.strategy.HLJAXBImportStrategy;
import de.homelabs.modules.tools.strategy.IHLImportStrategy;

/**
 * 
 * @author D.Mueller
 *
 * singleton
 */
@Service("hlFreeMarkerTemplateManager")
public class HLTemplateManager implements IHLTemplateManager {
	//Singeltion Design Pattern
	private static HLTemplateManager instance = new HLTemplateManager();
	
	//Vars
	private HLTemplateList templateList;
	
	//active open filereader
	//HashMap Key = templateKey
	private Map<String, Reader> activeReaders = new HashMap<String, Reader>();
	
	//Default to JAXB
	//private IHLTemplateImportStrategy importStrategy = new HLJAXBTemplateImportStrategy();
	private IHLImportStrategy<HLTemplateList> importStrategy = new HLJAXBImportStrategy<HLTemplateList>(HLTemplateList.class);
	
	//options
	private TemplateImportOption templateImportOption = TemplateImportOption.FIRST_LOAD;
	private boolean templateLoaded = false;
	
	/**
	 * private constructor
	 */
	private HLTemplateManager(){}
	
	/**
	 * singelton function
	 */
	public static HLTemplateManager getInstance(){
		return instance;
	}
	
	/****************
	 * function 	*
	 ****************/
	/*
	 * (non-Javadoc)
	 * @see de.homelabs.template.service.IHLTemplateManager#getTemplateReader(de.homelabs.template.domain.HLTemplateElement)
	 */
	public Reader getTemplateReader(HLTemplateElement templateElement) {
		//find template from classpath
		Reader reader = new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream(templateElement.getTemplateUrl()));
		
		//remind reader for close action
		activeReaders.put(templateElement.getTemplateKey(), reader);
		
		//return
		return reader;
	}
	
	/*
	 * (non-Javadoc)
	 * @see de.homelabs.template.service.IHLTemplateManager#closeTemplateReader(de.homelabs.template.domain.HLTemplateElement)
	 */
	public boolean closeTemplateReader(HLTemplateElement templateElement){
		//try to find assigned reader
		for (String templateKey : activeReaders.keySet()){
			if (templateElement.getTemplateKey().equalsIgnoreCase(templateKey)){
				//reader found
				Reader reader = activeReaders.get(templateKey);
				try {
					//close
					reader.close();
					return true;
				} catch (IOException e) {
					System.out.println(e);
					return false;
				}
			}
		}
		
		//no reader found
		return false;
	}
	
	/*
	 * (non-Javadoc)
	 * @see de.homelabs.template.service.IHLTemplateManager#findTemplate(java.lang.String)
	 */
	public HLTemplateElement findTemplate(String templateKey){
		//determine if we need to import template list
		if (templateLoaded == false || templateImportOption == TemplateImportOption.EVERY_REQUEST){
			if (importTemplateList()){
				this.templateLoaded = true;
			}
		}
		
		//loop over list
		for (HLTemplateElement el : this.templateList.getTemplates()){
			if (el.getTemplateKey().equals(templateKey)){
				return el;
			}
		} 
		
		//return 
		return null;
	}
	
	private boolean importTemplateList(){
		this.templateList = this.importStrategy.importElementList("/hltemplates.xml");
		return true;
	}
	/*******************
	 * getter / setter *
	 *******************/
	/*
	 * (non-Javadoc)
	 * @see de.homelabs.template.service.IHLTemplateManager#getTemplateList()
	 */
	public List<HLTemplateElement> getTemplateList() {
		return templateList.getTemplates();
	}

	/*
	 * (non-Javadoc)
	 * @see de.homelabs.template.service.IHLTemplateManager#setTemplateList(java.util.List)
	 */
	public void setTemplateList(List<HLTemplateElement> templateList) {
		this.templateList.setTemplates(templateList);
	}
	
//	public IHLTemplateImportStrategy getImportStrategy() {
//		return importStrategy;
//	}
//
//	public void setImportStrategy(IHLTemplateImportStrategy importStrategy) {
//		this.importStrategy = importStrategy;
//	}

	public TemplateImportOption getTemplateImportOption() {
		return templateImportOption;
	}

	public void setTemplateImportOption(TemplateImportOption templateImportOption) {
		this.templateImportOption = templateImportOption;
	}

	public boolean isTemplateLoaded() {
		return templateLoaded;
	}

	public void setTemplateLoaded(boolean templateLoaded) {
		this.templateLoaded = templateLoaded;
	}
	
	public IHLImportStrategy<HLTemplateList> getImportStrategy() {
		return importStrategy;
	}

	public void setImportStrategy(IHLImportStrategy<HLTemplateList> importStrategy) {
		this.importStrategy = importStrategy;
	}
	/************
	 * enums	*
	 ************/
	public enum TemplateImportOption {
		FIRST_LOAD, EVERY_REQUEST
	}
}
